#include "../头文件/Image.h"

bool show_bmp_image(char *bmp_path)
{
    int fd_fb = open("/dev/fb0", O_RDWR);
    if (fd_fb < 0)
    {
        perror("打开lcd_p屏失败");
        return false;
    }
    int *lcd_p = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
    if (lcd_p == MAP_FAILED)
    {
        close(fd_fb);
        perror("映射失败");
        return false;
    }

    int fd = open(bmp_path, O_RDWR);
    bmpfile_head_t file_head_info = {0};
    bmpbit_head_t bmp_head_info = {0};
    if (fd < 0)
    {
        printf("打开文件%s失败:%s\r\n", bmp_path, strerror(errno));
        return false;
    }
    read(fd, &file_head_info, sizeof(bmpfile_head_t)); // 读取文件信息头
    read(fd, &bmp_head_info, sizeof(bmpbit_head_t));   // 读取位图信息头
    // printf("文件类型: %#x\n文件大小: %d\n偏移量: %d\n",
    //        file_head_info.bfType, file_head_info.bfSize, file_head_info.bfOffBits);

    // printf("信息头的大小: %d\n图像的宽: %d\n图像的高度: %d\n像素的位数: %d\n",
    //        bmp_head_info.biSize, bmp_head_info.biWidth, bmp_head_info.biHeight, bmp_head_info.biBitCount);

    char ybuf[bmp_head_info.biWidth * 3];                // 一行的像素数据
    int pad = (4 - (bmp_head_info.biWidth * 3) % 4) % 4; // 补充的字节数（一行数据字节大小要满足4的倍数）
    for (int y = 0; y < bmp_head_info.biHeight; y++)     // 行
    {
        read(fd, ybuf, sizeof(ybuf)); // 读一行的像素数据
        lseek(fd, pad, SEEK_CUR);     // 跳过补充的字节数

        for (int x = 0; x < bmp_head_info.biWidth; x++) // 将一行的数据写入到lcd_p屏
        {
            // *(lcd_p + x + y * 800) =  A << 24 | R <<16  | G << 8 | B;
            *(lcd_p + x + (479 - y) * 800) = 0 << 24 |
                                             ybuf[2 + 3 * x] << 16 |
                                             ybuf[1 + 3 * x] << 8 |
                                             ybuf[0 + 3 * x];
        }
    }
    close(fd);
    return true;
}
/**
 * @brief 显示动态图片
 *
 * @param gif_path 动态图片的文件夹
 */
void show_gif_image(char *gif_path)
{
    DIR *fd_gif = opendir(gif_path);
    if (fd_gif == NULL)
    {
        perror("打开gif文件夹失败");
        return;
    }
    // 加载动态图片
    char *gif_image = malloc(256);
    for (int i = 0; i <= 300; ++i)
    {
        sprintf(gif_image, "%s/Frame%d.jpg", gif_path, i);
        show_anyjpg(0, 0, gif_image);
        show_progress_bar(3 * i);
        usleep(300);
        memset(gif_image, 0, sizeof(gif_image));
    }
}
/**
 * @brief 根据偏移量显示bmp图片
 * 
 * @param bmp_path 图片路径
 * @param index_x x的偏移量
 * @param index_y y的偏移量
 * @return true 成功
 * @return false 失败
 */
bool show_bmp_image2(char *bmp_path, int index_x, int index_y)
{
    int fd_fb = open("/dev/fb0", O_RDWR);
    if (fd_fb < 0)
    {
        perror("打开lcd_p屏失败");
        return false;
    }
    int *lcd_p = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
    if (lcd_p == MAP_FAILED)
    {
        close(fd_fb);
        perror("映射失败");
        return false;
    }

    int fd = open(bmp_path, O_RDWR);
    bmpfile_head_t file_head_info = {0};
    bmpbit_head_t bmp_head_info = {0};
    if (fd < 0)
    {
        printf("打开文件%s失败:%s\r\n", bmp_path, strerror(errno));
        return false;
    }
    read(fd, &file_head_info, sizeof(bmpfile_head_t)); // 读取文件信息头
    read(fd, &bmp_head_info, sizeof(bmpbit_head_t));   // 读取位图信息头
    // printf("文件类型: %#x\n文件大小: %d\n偏移量: %d\n",
    //        file_head_info.bfType, file_head_info.bfSize, file_head_info.bfOffBits);

    // printf("信息头的大小: %d\n图像的宽: %d\n图像的高度: %d\n像素的位数: %d\n",
    //        bmp_head_info.biSize, bmp_head_info.biWidth, bmp_head_info.biHeight, bmp_head_info.biBitCount);

    char ybuf[bmp_head_info.biWidth * 3];                // 一行的像素数据
    int pad = (4 - (bmp_head_info.biWidth * 3) % 4) % 4; // 补充的字节数（一行数据字节大小要满足4的倍数）
    for (int y = 0; y < bmp_head_info.biHeight; y++)     // 行
    {
        read(fd, ybuf, sizeof(ybuf)); // 读一行的像素数据
        lseek(fd, pad, SEEK_CUR);     // 跳过补充的字节数

        for (int x = 0; x < bmp_head_info.biWidth; x++) // 将一行的数据写入到lcd_p屏
        {
            // *(lcd_p + x + index_x + (bmp_head_info.biHeight - 1 - y + index_y) * 800)
            *(lcd_p + x + index_x + (479 - y + (index_y + bmp_head_info.biHeight) % 480) * 800) = 0 << 24 |
                                                                                                      ybuf[2 + 3 * x] << 16 |
                                                                                                      ybuf[1 + 3 * x] << 8 |
                                                                                                      ybuf[0 + 3 * x];
        }
    }
    close(fd);
    return true;
}
/**
 * @brief 显示bmp图片 连续使用映射地址的
 * 
 * @param path 
 * @param offset_x 
 * @param offset_y 
 * @param map 映射地址
 * @return int 
 */
int draw_image(const char *path, int offset_x, int offset_y, int (*map)[800])
{
    int img_fd = open(path, O_RDONLY);
    if (img_fd == -1)
    {
        perror("图片打开失败 \n");
        return -1;
    }
    int ret;
    // 度图片宽高信息
    bmpbit_head_t img_info;
    lseek(img_fd, 14, SEEK_SET);
    ret = read(img_fd, &img_info, sizeof(img_info));
    if (ret == -1)
    {
        perror("read 图片 info信息失败 \n");
        return -1;
    }
    int h = img_info.biHeight;
    int w = img_info.biWidth;
    // 读取图片像素信息
    char *bmp_colors = malloc(h * w * 3); // 堆记得回收他

    ret = read(img_fd, bmp_colors, h * w * 3);
    if (ret == -1)
    {
        perror("read 图片像素失败 \n");
        return -1;
    }

    // 开始渲染
    for (int y = 0; y < h; y++)
    {
        for (int x = 0; x < w; x++)
        {
            int index = (y * w + x) * 3;
            unsigned char b = bmp_colors[index + 0];
            unsigned char g = bmp_colors[index + 1];
            unsigned char r = bmp_colors[index + 2];
            //  这里是映射内存, 一修改lcd就会更新
            map[(h - 1 - y) + offset_y][x + offset_x] = 0xff << 24 | r << 16 | g << 8 | b;
        }
    }

    free(bmp_colors);
    close(img_fd);
    return 0;
}